﻿using System.Collections.Generic;
using System.Threading;
using AspectIntercept;
using GestorSQL.BLL.ImplementationsBridge;
using GestorSQL.BusinessEntities;
using GestorSQL.DAO;
using GestorSQL.DAO.FileManager;
using GestorSQL.DAO.InterceptDAO;

namespace GestorSQL.BLL
{
    [Intercept(InterceptAllMethods = true, PreProcesor = typeof(DBTraceProcessor), PostProcesor = typeof(DBTraceProcessor), OmitMethods = new string[] { })]
    public class SolutionManager : InterceptContext
    {
        #region Variables Privadas
        private IGestorSqlDao dao = new GestorSqlDao();
        private IFileManager fileManager = ImplementationBridge.GetFileManager("Compress");
        private CaseManager _caseManager = new CaseManager();


        #endregion

        #region Metodos Publicos
        /// <summary>
        /// Obtiene la solucion actual de acuerdo alcasoabirto.
        /// </summary>
        /// <param name="caso"></param>
        /// <returns></returns>
        [InterceptOmit]
        public Solucion GetSolucionByCase(Caso caso)
        {

            return dao.GetSolucionByCase(caso);

        }

        /// <summary>
        /// Abre el Query asociado con la solucion
        /// </summary>
        /// <param name="caso"></param>
        /// <returns></returns>
        public string OpenSolutionQuery(Caso caso)
        {
            return fileManager.GetFileData(PathGetter.GetProdPath(caso, caso.SolucionActual.Value), PathGetter.ORIGINAL);
        }

        /// <summary>
        /// Realiza el rechazo de la solucion desde la consola del Autorizador
        /// </summary>
        /// <param name="caso"></param>
        /// <param name="descripcion"></param>
        /// <returns></returns>
        public Resultado RechazarSolucion(Caso caso, string descripcion)
        {
            return _caseManager.SetStateCase(caso, descripcion, EstadoCaso.DevueltoDesdeAutorizacion);

        }

        /// <summary>
        /// Realiza la devolución de la solucion desde la consola del Analista 
        /// </summary>
        /// <param name="caso"></param>
        /// <param name="descripcion"></param>
        /// <returns></returns>
        public Resultado DevolverSolucion(Caso caso, string descripcion)
        {
            return _caseManager.SetStateCase(caso, descripcion, EstadoCaso.DevueltoDesdeEjecucion);
        }

        /// <summary>
        /// Se encarga de Cerrar el Caso en caso que la solución y ejecución sea la correcta segun el Ejecutor.
        /// </summary>
        /// <param name="caseNumber"></param>
        /// <returns></returns>
        public Resultado CerrarSolucion(string caseNumber, string descripcion)
        {

            Caso currentCase = _caseManager.GetCase(caseNumber);
            fileManager.CompressFile(PathGetter.GetProdPath(currentCase,currentCase.SolucionActual.Value), PathGetter.FINAL, PathGetter.FINAL);
            fileManager.CompressFile(PathGetter.GetProdPath(currentCase, currentCase.SolucionActual.Value), PathGetter.SALIDA, PathGetter.SALIDA);

            return _caseManager.SetStateCase(new Caso() { NumeroCaso = caseNumber }, "Caso Ejecutado Correctamente y Solucionado.", EstadoCaso.EjecutadoCorrectamente);


        }

        /// <summary>
        /// Registra los datos de a solucion previa autorizacion
        /// </summary>
        /// <param name="solucion"></param>
        /// <returns></returns>
        public Resultado AceptarSolution(Solucion solucion)
        {

            string descripcion = string.Empty;
            EstadoCaso estadoActual;

            if (dao.UpdateSolution(solucion).Equals(Resultado.Exitoso))
            {
                if (solucion.TipoEjecucion == 0)
                    estadoActual = EstadoCaso.AutorizadoAsistido;

                else
                    estadoActual = EstadoCaso.AutorizadoAutomatico;

                Caso currentCase = _caseManager.GetCase(solucion.Caso.NumeroCaso);
                currentCase.Conexion1 = new Conexion() { IdConexion = solucion.FK_Conexion };
                dao.SaveCase(currentCase);


                return _caseManager.SetStateCase(solucion.Caso, "Autorizado para ejecución", estadoActual);

            }
            else
                return Resultado.Fallido;

        }

        /// <summary>
        /// Guarda la solucion entegada por el analista
        /// </summary>
        /// <param name="solucion">Solucion del caso</param>
        /// <param name="conjuto">Conjunto ordenado de queries</param>
        /// <returns>Retorna el id de la solución guardada.
        /// Si no es posible guardar la solución retorna -1
        /// </returns>
        public long SaveAnalystSolution(Solucion solucion, List<ConjuntoSolucion> conjuntoSolucionList, string originalQuery)
        {

            long idSolucion = dao.SaveSolution(solucion);

            if (idSolucion != -1)
            {

                foreach (var conjunto in conjuntoSolucionList)
                    conjunto.FK_Solucion = idSolucion;

                dao.SaveConjuntosSolucion(conjuntoSolucionList);


                fileManager.SaveFile(PathGetter.GetProdPath(new Caso()
                {

                    SolucionActual = idSolucion,
                    UsuarioPruebas = Thread.CurrentPrincipal.Identity.Name,
                    NumeroCaso = solucion.FK_Caso

                }, idSolucion), PathGetter.ORIGINAL, originalQuery, true);

                return idSolucion;
            }

            return idSolucion;

        }

        /// <summary>
        /// Obtiene la solución original autorizada para ejecución en producción 
        /// </summary>
        /// <param name="caseNumber"></param>
        /// <returns></returns>
        public string GetOriginalSolution(string caseNumber, long idSolution)
        {
         

            return fileManager.GetFileData(PathGetter.GetProdPath(_caseManager.GetCase(caseNumber), idSolution), PathGetter.ORIGINAL);

        }

        /// <summary>
        /// Obtiene el Script de la Solucion Ejecutada en producción.
        /// </summary>
        /// <param name="caseNumber"></param>
        /// <param name="idSolution"></param>
        /// <returns></returns>
        public BLLDescompressReader GetFinalScriptSolution(string caseNumber, long idSolution)
        {
            Caso caso = _caseManager.GetCase(caseNumber);
            BLLDescompressReader bblDescompressReader = new BLLDescompressReader();
            bblDescompressReader.DescompressFile(PathGetter.GetProdPath(caso,idSolution), PathGetter.FINAL, PathGetter.FINAL);

            return bblDescompressReader;

        }

        /// <summary>
        /// Obtiene los resultados obtenidos al realizar las diferentes ejecuciones en producción.
        /// </summary>
        /// <param name="caseNumber"></param>
        /// <param name="idSolution"></param>
        /// <returns></returns>
        public BLLDescompressReader GetSalidaScriptSolution(string caseNumber, long idSolution)
        {
            Caso caso = _caseManager.GetCase(caseNumber);
            BLLDescompressReader bblDescompressReader = new BLLDescompressReader();
            bblDescompressReader.DescompressFile(PathGetter.GetProdPath(caso,idSolution), PathGetter.SALIDA, PathGetter.SALIDA);

            return bblDescompressReader;

        }

        /// <summary>
        /// Obtiene los registros de las ejecuciones en producción realizadas sobre la solución.
        /// </summary>
        /// <param name="idSolution"></param>
        /// <returns></returns>
        public List<Log> GetLogsByBySolution(long idSolution)
        {

            return dao.GetLogsByBySolution(idSolution);
        }

        #endregion

    }
}
